package com.yida.wy.vote.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.yida.common.core.constant.SecurityConstants;
import com.yida.common.core.domain.R;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.text.Convert;
import com.yida.common.core.utils.CheckRemoteServiceResultUtils;
import com.yida.common.core.utils.StringUtils;
import com.yida.gwj.api.domain.dto.GwjGVoteProjectStatisticsDataDTO;
import com.yida.system.api.RemoteAreaService;
import com.yida.system.api.domain.SysArea;
import com.yida.wy.common.domain.WyBaseCommunity;
import com.yida.wy.common.enums.WyBusinessHouseStatus;
import com.yida.wy.common.utils.CheckDiffList;
import com.yida.wy.vote.domain.*;
import com.yida.wy.vote.domain.dto.WyVoteProjectStatisticsBaseDataDTO;
import com.yida.wy.vote.domain.dto.WyVoteResultDTO;
import com.yida.wy.vote.domain.dto.WyVoteResultDetailItemDTO;
import com.yida.wy.vote.domain.dto.WyVoteResultDetailOptionCountDTO;
import com.yida.wy.vote.domain.vo.WyVoteItemVo;
import com.yida.wy.vote.enums.WyVoteAgreeFlagEnum;
import com.yida.wy.vote.service.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 投票项目Service业务层处理
 *
 * @author lqq
 * @date 2023-03-13
 */
@Service
public class WyVoteStatisticsServiceImpl implements IWyVoteStatisticsService {

    @Resource
    private IWyVoteProjectService voteProjectService;

    @Resource
    private IWyVoteResultService voteResultService;

    @Resource
    private IWyVoteResultDetailService voteResultDetailService;

    @Resource
    private IWyVoteTemplateService voteTemplateService;

    @Resource
    private RemoteAreaService remoteAreaService;

    @Resource
    private IWyBusinessDataService gwjBaseDataService;


    /**
     * 公维金投票项目统计
     *
     * @param voteId 投票ID
     * @return 结果
     */
    @Override
    public GwjGVoteProjectStatisticsDataDTO gVoteProjectStatistics(Long voteId) {
        //查询投票
        WyVoteProject project = voteProjectService.selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(project)) {
            throw new ServiceException("查无投票信息");
        }
        GwjGVoteProjectStatisticsDataDTO dto = new GwjGVoteProjectStatisticsDataDTO();
        //所有业主数据
        List<WyVoteResultDTO> owners = voteResultService.selectVoteResultDtoList(new WyVoteResultDTO() {{
            setVoteId(voteId);
            setSelectFlag(WyBusinessHouseStatus.CONFIRM.getCode());
        }});
        //业主总人数
        List<WyVoteResultDTO> ownerList = getValidVoteOwnerList(owners);
        dto.setTotalOwner(Convert.toInt(ownerList.size(), 0));
        //专有部分总面积
        dto.setTotalSize(voteHouseSizeStatisticsByOwner(owners));
        //参与表决业主人数
        int validVoteCount = voteResultDetailService.countVoteOwnerByVoteId(voteId);
        dto.setTotalValidOwner(validVoteCount);
        //表决业主占比
        dto.setOwnerPercent(dto.getTotalOwner() == 0 ? BigDecimal.ZERO : Convert.toBigDecimal(dto.getTotalValidOwner()).divide(Convert.toBigDecimal(dto.getTotalOwner()), 2, RoundingMode.HALF_UP));
        //表决业主建筑总面积
        List<WyVoteHouse> validHouses = voteResultDetailService.selectVoteResultHouseListByVoteId(voteId);
        dto.setTotalValidSize(this.voteHouseSizeStatisticsByHouse(validHouses));
        //表决业主面积占比
        dto.setSizePercent(dto.getTotalSize().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : dto.getTotalValidSize().divide(dto.getTotalSize(), 2, RoundingMode.HALF_UP));
        //同意业主人数
        int agreeVoteCount = voteResultDetailService.countAgreeVoteOwnerByVoteId(voteId);
        dto.setAgreeOwner(agreeVoteCount);
        //同意人数占比
        dto.setAgreeOwnerPercent(dto.getTotalValidOwner() == 0 ? BigDecimal.ZERO : Convert.toBigDecimal(dto.getAgreeOwner()).divide(Convert.toBigDecimal(dto.getTotalValidOwner()), 2, RoundingMode.HALF_UP));
        //同意业主建筑总面积
        List<WyVoteHouse> agreeHouses = voteResultDetailService.selectVoteResultHouseList(new WyVoteResultDetail() {{
            setVoteId(voteId);
            setAgreeFlag(WyVoteAgreeFlagEnum.AGREE.getCode());
        }});
        dto.setAgreeTotalSize(this.voteHouseSizeStatisticsByHouse(agreeHouses));
        //同意面积占比
        dto.setAgreeSizePercent(dto.getTotalValidSize().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : dto.getAgreeTotalSize().divide(dto.getTotalValidSize(), 2, RoundingMode.HALF_UP));
        return dto;
    }

    /**
     * 统计投票基础数据
     *
     * @param voteId 投票ID
     * @return /
     */
    public WyVoteProjectStatisticsBaseDataDTO eVoteProjectStatisticsBaseData(Long voteId) {
        //查询投票
        WyVoteProject project = voteProjectService.selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(project)) {
            throw new ServiceException("查无投票信息");
        }
        WyVoteProjectStatisticsBaseDataDTO dto = new WyVoteProjectStatisticsBaseDataDTO();
        //所有业主数据
        List<WyVoteResultDTO> owners = voteResultService.selectVoteResultDtoList(new WyVoteResultDTO() {{
            setVoteId(voteId);
            setSelectFlag(WyBusinessHouseStatus.CONFIRM.getCode());
        }});
        //统计业主总人数、总表决票
        List<WyVoteResultDTO> ownerList = getValidVoteOwnerList(owners);
        dto.setTotalOwner(Convert.toInt(ownerList.size(), 0));
        //统计建筑总面积
        dto.setTotalSize(this.voteHouseSizeStatisticsByOwner(owners));
        //统计有效票、收回表决票、有效业主人数
        int validVoteCount = getValidVoteOwnerNum(ownerList);
        dto.setTotalValidOwner(validVoteCount);
        //计算业主占比
        dto.setOwnerPercent(dto.getTotalOwner() == 0 ? BigDecimal.ZERO : Convert.toBigDecimal(validVoteCount).divide(Convert.toBigDecimal(dto.getTotalOwner()), 2, RoundingMode.HALF_UP));
        //统计有效建筑总面积
        List<WyVoteHouse> validHouses = voteResultDetailService.selectVoteResultHouseListByVoteId(voteId);
        dto.setTotalValidSize(this.voteHouseSizeStatisticsByHouse(validHouses));
        //计算有效面积占比
        dto.setSizePercent(dto.getTotalSize().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : dto.getTotalValidSize().divide(dto.getTotalSize(), 2, RoundingMode.HALF_UP));
        //计算弃权票
        dto.setTotalAbstentionCount(dto.getTotalOwner() - dto.getTotalValidOwner());
        //地区
        dto.setAreaId(project.getAreaId());
        R<SysArea> areaR = remoteAreaService.getVoteAreaInfo(project.getAreaId(), SecurityConstants.INNER);
        dto.setAreaName(CheckRemoteServiceResultUtils.isSuccessWithData(areaR) ? areaR.getData().getAreaName() : "");
        //街道
        dto.setStreetId(project.getStreetId());
        R<SysArea> streetR = remoteAreaService.getVoteAreaInfo(project.getStreetId(), SecurityConstants.INNER);
        dto.setStreetName(CheckRemoteServiceResultUtils.isSuccessWithData(streetR) ? streetR.getData().getAreaName() : "");
        //小区
        dto.setCommunityId(project.getCommunityId());
        WyBaseCommunity community = gwjBaseDataService.selectGwjBaseCommunityByGwjBaseCommunityId(project.getCommunityId());
        dto.setCommunityName(StringUtils.isNull(community) ? "" : community.getCommunityName());
        return dto;
    }

    /**
     * 查询票数详细
     *
     * @param voteId 投票ID
     * @return /
     */
    @Override
    public List<WyVoteResultDetailItemDTO> voteResultDetailStatistics(Long voteId) {
        if (StringUtils.isNull(voteProjectService.selectVoteProjectByVoteId(voteId))) {
            throw new ServiceException("操作失败,查无投票信息");
        }
        //所有业主数据
        List<WyVoteResultDTO> owners = voteResultService.selectVoteResultDtoList(new WyVoteResultDTO() {{
            setVoteId(voteId);
            setSelectFlag(WyBusinessHouseStatus.CONFIRM.getCode());
        }});
        //统计业主总人数、总表决票
        List<WyVoteResultDTO> ownerList = getValidVoteOwnerList(owners);
        //有效总投票数
        int validVoteCount = getValidVoteOwnerNum(ownerList);
        //获取模板信息
        List<WyVoteItemVo> voteItemVos = templateJsonToList(voteId);
        //统计投票选项的结果
        return voteItemVos.stream().map(iv -> {
            WyVoteResultDetailItemDTO itemDto = new WyVoteResultDetailItemDTO();
            itemDto.setItemId(iv.getItemId());
            itemDto.setItemName(iv.getItemName());
            List<WyVoteResultDetailOptionCountDTO> optionDto = BeanUtil.copyToList(iv.getContent(), WyVoteResultDetailOptionCountDTO.class);
            optionDto.forEach(o -> {
                //有效总票数
                o.setValidVoteCount(validVoteCount);
                //投票数
                List<WyVoteResult> results = voteResultDetailService.selectVoteOwnerListByOptionId(o.getOptionId());
                //电话去重
                List<WyVoteResult> ownersByPhone = results.stream().filter(CheckDiffList.distinctByKey(WyVoteResult::getOwnerPhone)).collect(Collectors.toList());
                //身份证去重
//                List<WyVoteResult> ownersByCard = ownersByPhone.stream().filter(CheckDiffList.distinctByKey(WyVoteResult::getCardNum)).collect(Collectors.toList());
                o.setVoteCount(ownersByPhone.size());
                //计算票数占比
                o.setVoteNumPercent(validVoteCount == 0 ? BigDecimal.ZERO : Convert.toBigDecimal(o.getVoteCount()).divide(Convert.toBigDecimal(validVoteCount), 2, RoundingMode.HALF_UP));
                //得票权数（建筑面积）㎡
                List<WyVoteHouse> voteHouses = voteResultDetailService.selectVoteResultHouseList(new WyVoteResultDetail() {{
                    setOptionId(o.getOptionId());
                    setVoteId(voteId);
                }});
                //得票面积
                o.setTotalSize(this.voteHouseSizeStatisticsByHouse(voteHouses));
            });
            itemDto.setOptions(optionDto);
            return itemDto;
        }).collect(Collectors.toList());
    }

    /**
     * 获取有效的业主集合
     *
     * @param owners 投票ID
     * @return /
     */
    private List<WyVoteResultDTO> getValidVoteOwnerList(List<WyVoteResultDTO> owners) {

        //电话去重
        List<WyVoteResultDTO> ownersByPhone = owners.stream().filter(CheckDiffList.distinctByKey(WyVoteResultDTO::getOwnerPhone)).collect(Collectors.toList());
        //身份证去重
//        List<WyVoteResultDTO> ownersByCard = ownersByPhone.stream().filter(CheckDiffList.distinctByKey(WyVoteResultDTO::getCardNum)).collect(Collectors.toList());
        return ownersByPhone;
    }

    /**
     * 获取有效的已投票业主数
     *
     * @param owners 有效业主
     * @return /
     */
    private Integer getValidVoteOwnerNum(List<WyVoteResultDTO> owners) {
        AtomicReference<Integer> num = new AtomicReference<>(0);
        owners.forEach(o->{
            if (ObjUtil.isNotNull(o.getVoteTime())){
                num.updateAndGet(v -> v + 1);
            }
        });
        return num.get();
    }

    /**
     * 计算房屋面积，现房面积优先
     *
     * @param houses 房屋集合
     * @return /
     */
    private BigDecimal voteHouseSizeStatisticsByHouse(List<WyVoteHouse> houses) {
        if (StringUtils.isEmpty(houses)) {
            return BigDecimal.ZERO;
        }
        return houses.stream().map(h -> {
            if (StringUtils.isNotNull(h.getActualSize()) && h.getActualSize().compareTo(BigDecimal.ZERO) != 0) {
                return h.getActualSize();
            } else {
                return StringUtils.isNotNull(h.getForecastSize()) ? h.getForecastSize() : BigDecimal.ZERO;
            }
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 计算房屋面积，现房面积优先
     *
     * @param houses 房屋集合
     * @return /
     */
    private BigDecimal voteHouseSizeStatisticsByOwner(List<WyVoteResultDTO> houses) {
        if (StringUtils.isEmpty(houses)) {
            return BigDecimal.ZERO;
        }
        return houses.stream().map(h -> {
            if (StringUtils.isNotNull(h.getActualSize()) && h.getActualSize().compareTo(BigDecimal.ZERO) != 0) {
                return h.getActualSize();
            } else {
                return StringUtils.isNotNull(h.getForecastSize()) ? h.getForecastSize() : BigDecimal.ZERO;
            }
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 查询投票选项模板并转为对象
     *
     * @param voteId 投票ID
     * @return /
     */
    private List<WyVoteItemVo> templateJsonToList(Long voteId) {
        //获取模板并转化为对象
        WyVoteTemplate template = voteTemplateService.selectVoteTemplateByVoteId(voteId);
        if (StringUtils.isNull(template)) {
            throw new ServiceException("查无投票选项信息");
        }
        return JSONUtil.toList(template.getTemplateJson(), WyVoteItemVo.class);
    }
}